package com.clei.utils;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;

/**
 * IP工具类
 *
 * @author KIyA
 */
public class IPUtil {

    /**
     * 需要忽略的接口名
     */
    private static String[] ignoredInterfaces = {};

    /**
     * 返回第一个非回环地址 抄的Spring-cloud-common-2.2.2.RELEASE.jar InetUtils源码
     *
     * @return
     */
    public static InetAddress findFirstNonLoopbackAddress() {
        InetAddress result = null;
        try {
            int lowest = Integer.MAX_VALUE;
            for (Enumeration<NetworkInterface> nics = NetworkInterface
                    .getNetworkInterfaces(); nics.hasMoreElements(); ) {
                NetworkInterface ifc = nics.nextElement();
                if (ifc.isUp()) {
                    PrintUtil.log("Testing interface: " + ifc.getDisplayName());
                    if (ifc.getIndex() < lowest || result == null) {
                        lowest = ifc.getIndex();
                    } else if (result != null) {
                        continue;
                    }

                    // @formatter:off
                    if (!ignoreInterface(ifc.getDisplayName())) {
                        for (Enumeration<InetAddress> addrs = ifc
                                .getInetAddresses(); addrs.hasMoreElements(); ) {
                            InetAddress address = addrs.nextElement();

                            PrintUtil.log("displayName : {}, hostName : {}, address : {}, ipV4 : {}, loopBack : {}", ifc.getDisplayName(), address.getHostName(), address.getHostAddress(), (address instanceof Inet4Address), address.isLoopbackAddress());

                            if (address instanceof Inet4Address
                                    && !address.isLoopbackAddress()) {
                                PrintUtil.log("Found non-loopback interface: "
                                        + ifc.getDisplayName());
                                result = address;
                            }
                        }
                    }
                    // @formatter:on
                }
            }
        } catch (IOException ex) {
            PrintUtil.log("Cannot get first non-loopback address", ex);
        }

        if (result != null) {
            return result;
        }

        try {
            return InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            PrintUtil.log("Unable to retrieve localhost");
        }

        return null;
    }

    /**
     * 本机ip
     *
     * @return Ip
     */
    public static String getIp() {
        List<String> list = new ArrayList<>(100);
        CmdUtil.exec("ipconfig", list::add, PrintUtil::println);
        List<List<String>> lists = new ArrayList<>(4);
        int size = list.size();
        String name = null;
        List<String> l = null;
        boolean secondEmpty = false;
        for (int i = 4; i < size; i++) {
            String content = list.get(i);
            content = content.trim();
            if (null == name) {
                name = content;
                l = new ArrayList<>(4);
                lists.add(l);
                l.add(name);
                continue;
            }
            if (StringUtil.isEmpty(content)) {
                if (secondEmpty) {
                    secondEmpty = false;
                    name = null;
                } else {
                    secondEmpty = true;
                }
                continue;
            }
            if (content.startsWith("IPv4") || content.startsWith("子网掩码") || content.startsWith("默认网关")) {
                l.add(content);
            }
        }
        // IPv4
        lists = lists.stream()
                .filter(ll -> 4 == ll.size() && !ll.get(3).endsWith(":"))
                .collect(Collectors.toList());
        for (List<String> strings : lists) {
            strings.forEach(PrintUtil::println);
        }
        // 直接取第一个
        if (CollectionUtil.isEmpty(lists)) {
            return null;
        }
        List<String> strings = lists.get(0);
        String ipv4 = strings.get(1);
        return ipv4.split(":")[1].trim();
    }

    /**
     * 判断是否忽略
     *
     * @param interfaceName
     * @return
     */
    private static boolean ignoreInterface(String interfaceName) {
        for (String regex : ignoredInterfaces) {
            if (interfaceName.matches(regex)) {
                PrintUtil.log("Ignoring interface: " + interfaceName);
                return true;
            }
        }
        return false;
    }
}
